package programmierung.aufgabe3;

import java.util.Random;

import de.pdbm.ewn.Direction;
import de.pdbm.ewn.Game;
import de.pdbm.ewn.Number;
import de.pdbm.ewn.RedOrBlue;

public class EWN implements Game {
	private String[][] spielFeld;
	private Random rand;

	public EWN() {
		spielFeld = new String[5][5];
		rand = new Random();
	}

	@Override
	public String[][] getState() {
		String[][] retState = new String[25][4];
		String[] split = null;
		int retIndex = 0;
		int trimIndex = 0;

		for (int i = 0; i < spielFeld.length; i++) {
			for (int j = 0; j < spielFeld[0].length; j++) {
				if (spielFeld[i][j] != null) {
					split = spielFeld[i][j].split(" ");
					for (int x = 0; x < split.length; x++) {
						retState[retIndex][x] = split[x];
					}
					trimIndex++;
				}
				retIndex++;
			}
		}
		return trimArray(trimIndex, retState);
	}

	public String[][] trimArray(int length, String[][] uTArray) {
		String[][] trimmedA = new String[length][4];
		int tempIndex = 0;
		boolean addFlag = false;
		for (int i = 0; i < uTArray.length; i++) {
			for (int j = 0; j < uTArray[i].length; j++) {
				if (uTArray[i][0] != null) {
					trimmedA[tempIndex][j] = uTArray[i][j];
					addFlag = true;
				}
			}
			if (addFlag) {
				tempIndex++;
				addFlag = false;
			}
		}
		return trimmedA;
	}

	@Override
	public void init(RedOrBlue spieler, Number steinNum, int xPos, int yPos)
			throws IllegalArgumentException {

		if (isWithinSA(xPos - 1) && isWithinA(5 - yPos)) {
			spielFeld[spielFeld.length - yPos][xPos - 1] = buildDataString(
					spieler, steinNum, xPos, yPos);
		} else {
			throw new IllegalArgumentException();
		}

	}

	private String buildDataString(RedOrBlue farbe, Number steinNum, int xPos,
			int yPos) {
		StringBuffer strBuffer = new StringBuffer();
		strBuffer.append(farbe.name());
		strBuffer.append(" ");
		strBuffer.append(steinNum.name());
		strBuffer.append(" ");
		strBuffer.append(xPos);
		strBuffer.append(" ");
		strBuffer.append(yPos);

		return strBuffer.toString();
	}

	private boolean isWithinSA(int index) {
		if (index > -1 && index < spielFeld[0].length) {
			return true;
		} else {
			return false;
		}
	}

	private boolean isWithinA(int index) {
		if (index > -1 && index < spielFeld.length) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public Boolean isWinner(RedOrBlue farbe) {

		if (farbe.name().contains("BLUE")) {
			if (spielFeld[0][0] != null) {
				if (spielFeld[0][0].split(" ")[0].contentEquals("BLUE")) {
					return true;
				}
			}
			if (isClear(farbe)) {
				return true;
			}
		} else {// Red
			if (spielFeld[spielFeld.length - 1][spielFeld.length - 1] != null) {
				if (spielFeld[spielFeld.length - 1][spielFeld.length - 1]
						.split(" ")[0].contentEquals("RED")) {
					return true;
				}
			}
			if (isClear(farbe)) {
				return true;
			}
		}

		return false;
	}

	private boolean isClear(RedOrBlue farbe) {
		String[] tempStr = null;
		if (farbe.name().contains("BLUE")) { // check for red empty
			for (int i = 0; i < spielFeld.length; i++) {
				for (int j = 0; j < spielFeld[i].length; j++) {
					if (spielFeld[i][j] != null) {
						tempStr = spielFeld[i][j].split(" ");
						if (tempStr.length > 2
								&& tempStr[0].contentEquals("RED")) {
							return false;
						}
					}

				}
			}
		} else { // check for blue empty
			for (int i = 0; i < spielFeld.length; i++) {
				for (int j = 0; j < spielFeld[i].length; j++) {
					if (spielFeld[i][j] != null) {
						tempStr = spielFeld[i][j].split(" ");
						if (tempStr.length > 2
								&& tempStr[0].contentEquals("BLUE")) {
							return false;
						}
					}

				}
			}
		}

		return true;
	}

	@Override
	public void move(RedOrBlue farbe, Number steinNum, Direction direction)
			throws IllegalArgumentException {
		int[] indexes = searchIndex(farbe, steinNum);
		if (indexes != null) {
			switch (farbe.name()) {
			case "BLUE":
				switch (direction.name()) {
				case "VERTICAL": // UP
					if (isWithinSA(indexes[0] - 1) && isWithinA(indexes[1])) {
						spielFeld[indexes[0] - 1][indexes[1]] = buildDataString(
								farbe, steinNum, indexes[1] + 1,
								spielFeld.length - indexes[0] + 1);
					} else {
						throw new IllegalArgumentException();
					}
					break;
				case "HORIZONTAL": // LEFT
					if (isWithinSA(indexes[0]) && isWithinA(indexes[1] - 1)) {
						spielFeld[indexes[0]][indexes[1] - 1] = buildDataString(
								farbe, steinNum, indexes[1], spielFeld.length
										- indexes[0]);
					} else {
						throw new IllegalArgumentException();
					}
					break;
				case "DIAGONAL": // UP+LEFT
					if (isWithinSA(indexes[0] - 1) && isWithinA(indexes[1] - 1)) {
						spielFeld[indexes[0] - 1][indexes[1] - 1] = buildDataString(
								farbe, steinNum, indexes[1], spielFeld.length
										- indexes[0] + 1);
					} else {
						throw new IllegalArgumentException();
					}
					break;
				}
				break;
			case "RED":
				switch (direction.name()) {
				case "VERTICAL": // DOWN
					if (isWithinSA(indexes[0] + 1) && isWithinA(indexes[1])) {
						spielFeld[indexes[0] + 1][indexes[1]] = buildDataString(
								farbe, steinNum, indexes[1] + 1,
								spielFeld.length - indexes[0] - 1);
					} else {
						throw new IllegalArgumentException();
					}
					break;
				case "HORIZONTAL": // RIGHT
					if (isWithinSA(indexes[0]) && isWithinA(indexes[1] + 1)) {
						spielFeld[indexes[0]][indexes[1] + 1] = buildDataString(
								farbe, steinNum, indexes[1] + 2,
								spielFeld.length - indexes[0]);
					} else {
						throw new IllegalArgumentException();
					}
					break;
				case "DIAGONAL": // DOWN+RIGHT
					if (isWithinSA(indexes[0] + 1) && isWithinA(indexes[1] + 1)) {
						spielFeld[indexes[0] + 1][indexes[1] + 1] = buildDataString(
								farbe, steinNum, indexes[1] + 2,
								spielFeld.length - indexes[0] - 1);
					} else {
						throw new IllegalArgumentException();
					}
					break;
				}
				break;
			}
			spielFeld[indexes[0]][indexes[1]] = null;
		} else {
			throw new IllegalArgumentException();
		}
	}

	private int[] searchIndex(RedOrBlue farbe, Number steinNum) {
		String[] tempStr = null;
		for (int i = 0; i < spielFeld.length; i++) {
			for (int j = 0; j < spielFeld[i].length; j++) {
				if (spielFeld[i][j] != null) {
					tempStr = spielFeld[i][j].split(" ");
					if (tempStr.length > 2
							&& tempStr[0].contentEquals(farbe.name())
							&& tempStr[1].contains(steinNum.name())) {
						return new int[] { i, j };
					}
				}

			}
		}
		return null;
	}

	@Override
	public Number wuerfeln() {
		switch (rand.nextInt(6) + 1) {
		case 1:
			return Number.ONE;
		case 2:
			return Number.TWO;
		case 3:
			return Number.THREE;
		case 4:
			return Number.FOUR;
		case 5:
			return Number.FIVE;
		case 6:
			return Number.SIX;
		default:
			return null;
		}
	}

}
